﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI;
using YArchitech.LIB;
using YArchitech.ProgressBar;
using YArchitech.Revit;
using YJKArchKernel.OutWallSearch;
using YJKStairs.CommonUnit;

namespace ModelValidation.FireCompartment
{
	public partial class ViewPlanElemTreeViewForm : System.Windows.Forms.Form
	{
		public ViewPlanElemTreeViewForm(ExternalCommandData cmdData, List<ViewPlan> lstViewPlan, ViewPlanElemTreeViewForm.ECheckType eCheckType = ViewPlanElemTreeViewForm.ECheckType.eCheckFireDoorFlipFacing)
		{
			this.m_cmdData = cmdData;
			this.m_lstViewPlan = lstViewPlan;
			this.m_eCheckType = eCheckType;
			this.InitializeComponent();
		}

		public List<NotDimedDoorWithView> GetSelectedDoors()
		{
			return this.m_notDimedDoors;
		}

		private Document Doc
		{
			get
			{
				return this.m_cmdData.Application.ActiveUIDocument.Document;
			}
		}

		public List<ElementId> ElemIDs
		{
			get
			{
				return this.m_lstElemIDs;
			}
		}

		private bool ReadDlgData()
		{
			try
			{
				string path = Path.GetTempPath() + this.Text + ".dat";
				if (!File.Exists(path))
				{
					base.StartPosition = FormStartPosition.CenterScreen;
					return false;
				}
				base.StartPosition = FormStartPosition.Manual;
				FileStream fileStream = new FileStream(path, FileMode.Open);
				StreamReader streamReader = new StreamReader(fileStream);
				streamReader.BaseStream.Seek(0L, SeekOrigin.Begin);
				int x = Convert.ToInt32(streamReader.ReadLine());
				int y = Convert.ToInt32(streamReader.ReadLine());
				base.Location = new System.Drawing.Point(x, y);
				streamReader.Close();
				fileStream.Close();
				return true;
			}
			catch
			{
			}
			return false;
		}

		private void WriteDlgData()
		{
			try
			{
				FileStream fileStream = new FileStream(Path.GetTempPath() + this.Text + ".dat", FileMode.Create);
				StreamWriter streamWriter = new StreamWriter(fileStream);
				streamWriter.WriteLine(base.Location.X);
				streamWriter.WriteLine(base.Location.Y);
				streamWriter.Flush();
				streamWriter.Close();
				fileStream.Close();
			}
			catch
			{
			}
		}

		private void InitDlgDataByDef()
		{
			base.StartPosition = FormStartPosition.CenterScreen;
		}

		private void UpdateTreeNodeCheckStatus(bool bCheck)
		{
			this.UpdateTreeNodeCheckStatus(this.treeView.Nodes, bCheck);
		}

		private void UpdateTreeNodeCheckStatus(TreeNodeCollection treeNodes, bool bCheck)
		{
			foreach (object obj in treeNodes)
			{
				TreeNode treeNode = (TreeNode)obj;
				this.UpdateTreeNodeCheckStatus(treeNode.Nodes, bCheck);
				treeNode.Checked = bCheck;
			}
		}

		private void ReverseTreeNodeCheckStatus(TreeNodeCollection treeNodes)
		{
			foreach (object obj in treeNodes)
			{
				TreeNode treeNode = (TreeNode)obj;
				treeNode.Checked = !treeNode.Checked;
				this.ReverseTreeNodeCheckStatus(treeNode.Nodes);
			}
		}

		private void InitTreeViewByDoorFlipFacing()
		{
			try
			{
				List<ViewPlan> list = (from Autodesk.Revit.DB.ViewPlan v in new FilteredElementCollector(this.Doc).OfClass(typeof(ViewPlan))
				where !v.IsTemplate
				select v).ToList<ViewPlan>();
				List<ElementId> list2 = (from e in list
				select e.GenLevel.Id).Distinct<ElementId>().ToList<ElementId>();
				list2.Sort(new ViewPlanElemTreeViewForm.LevelIdComparer(this.Doc));
				List<ElementId> list3 = (from e in this.m_lstViewPlan
				select e.GenLevel.Id).Distinct<ElementId>().ToList<ElementId>();
				List<FamilyInstance> docFlipFacingFireDoors = this.GetDocFlipFacingFireDoors();
				ProgressBarForm progressBarForm = new ProgressBarForm(list2.Count, ProgressBarStyle.Blocks, true);
				progressBarForm.Text = "楼层防火门检测中...";
				progressBarForm.ShowInTaskbar = false;
				progressBarForm.Show();
				using (List<ElementId>.Enumerator enumerator = list2.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						ElementId idLevel = enumerator.Current;
						ViewPlan viewPlan = list.Find((ViewPlan e) => e.GenLevel.Id == idLevel);
						List<Stairs> levelStairs = this.GetLevelStairs(viewPlan.Id);
						IEnumerable<FamilyInstance> source = from door in docFlipFacingFireDoors
						where door.LevelId == idLevel
						select door;
						List<FamilyInstance> lstLevelInvalidFireDoors = new List<FamilyInstance>();
						if (list3.FindIndex((ElementId e) => e == idLevel) > -1)
						{
							List<Wall> source2 = new List<Wall>();
							List<bool> list4 = new List<bool>();
							if (OutWallFilter.Search(this.Doc, viewPlan.Id, ref source2, ref list4, false))
							{
								List<ElementId> list5 = (from e in source2
								select e.Id).ToList<ElementId>();
								for (int i = 0; i < list5.Count; i++)
								{
									ElementId idOutWall = list5[i];
									foreach (FamilyInstance familyInstance in from door in source
									where door.Host.Id == idOutWall
									select door)
									{
										if (!this.IsFireDoorFlipFacingOutsideRoom(familyInstance, idOutWall, list4[i]))
										{
											lstLevelInvalidFireDoors.Add(familyInstance);
										}
									}
								}
							}
							List<FamilyInstance> collection = (from door in this.GetInvalidFireDoorsByLevelStairsRoom(viewPlan.Id, viewPlan.GenLevel, levelStairs, source.ToList<FamilyInstance>(), true)
							where lstLevelInvalidFireDoors.Find((FamilyInstance e) => e.Id == door.Id) == null
							select door).ToList<FamilyInstance>();
							lstLevelInvalidFireDoors.AddRange(collection);
						}
						else
						{
							List<FamilyInstance> invalidFireDoorsByLevelStairsRoom = this.GetInvalidFireDoorsByLevelStairsRoom(viewPlan.Id, viewPlan.GenLevel, levelStairs, source.ToList<FamilyInstance>(), false);
							lstLevelInvalidFireDoors.AddRange(invalidFireDoorsByLevelStairsRoom);
						}
						if (lstLevelInvalidFireDoors.Count > 0)
						{
							TreeNode treeNode = this.treeView.Nodes.Add(viewPlan.GenLevel.Name);
							treeNode.Tag = viewPlan;
							foreach (FamilyInstance familyInstance2 in lstLevelInvalidFireDoors)
							{
								treeNode.Nodes.Add(familyInstance2.Symbol.Name).Tag = familyInstance2;
							}
						}
						progressBarForm.RefreshProgressBar();
						if (progressBarForm.m_stopTag)
						{
							break;
						}
					}
				}
				this.treeView.ExpandAll();
				this.treeView.Refresh();
			}
			catch
			{
			}
		}

		private bool IsFireDoorFlipFacingOutsideRoom(FamilyInstance fiFireDoor, ElementId idWall, bool bWallOrientIsOutside)
		{
			try
			{
				Wall wall = fiFireDoor.Document.GetElement(idWall) as Wall;
				XYZ xyz = wall.Orientation * (double)(bWallOrientIsOutside ? 1 : -1);
				Arc arc = (wall.Location as LocationCurve).Curve as Arc;
				if (arc != null)
				{
					XYZ center = arc.Center;
					bool flag = GeoUtil.IsParallel(arc.GetEndPoint(0) - center, xyz);
					xyz = (arc.Evaluate(0.5, true) - center).Normalize() * (double)(flag ? 1 : -1);
				}
				return GeoUtil.IsEqual(fiFireDoor.FacingOrientation.DotProduct(xyz), 1.0);
			}
			catch
			{
			}
			return true;
		}

		private bool IsFireDoorFlipFacingOutsideRoom(FamilyInstance fiFireDoor, Room room)
		{
			try
			{
				XYZ xyz = fiFireDoor.FacingOrientation.Normalize();
				double num = AssistFunc.mmToFeet(800.0);
				XYZ xyz2 = (fiFireDoor.Location as LocationPoint).Point;
				Level level = room.Document.GetElement(room.LevelId) as Level;
				xyz2 = new XYZ(xyz2.X, xyz2.Y, level.Elevation);
				xyz2 += xyz * num;
				return !room.IsPointInRoom(xyz2);
			}
			catch
			{
			}
			return false;
		}

		private void ZoomSelElem(Element elem)
		{
			try
			{
				string text = this.treeView.SelectedNode.Parent.Text;
				ViewPlan viewPlan = this.treeView.SelectedNode.Parent.Tag as Autodesk.Revit.DB.ViewPlan;
				if (viewPlan != null)
				{
					this.m_cmdData.Application.ActiveUIDocument.ActiveView = viewPlan;
					UIDocument activeUIDocument = this.m_cmdData.Application.ActiveUIDocument;
					RevitVersionFuncs.ClearSelection(activeUIDocument.Selection);
					RevitVersionFuncs.AddToSelection(activeUIDocument.Selection, elem);
					activeUIDocument.ShowElements(elem);
				}
			}
			catch
			{
			}
		}

		private List<FamilyInstance> GetDocFlipFacingFireDoors()
		{
			return new FilteredElementCollector(this.Doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Doors).Cast<FamilyInstance>().Where(new Func<FamilyInstance, bool>(UtilityTools.IsValidFlipFacingFireDoor)).ToList<FamilyInstance>();
		}

		private List<Stairs> GetLevelStairs(ElementId idView)
		{
			return new FilteredElementCollector(this.Doc, idView).OfClass(typeof(Stairs)).Cast<Stairs>().ToList<Stairs>();
		}

		private List<FamilyInstance> GetInvalidFireDoorsByLevelStairsRoom(ElementId idView, Level level, List<Stairs> lstStairs, List<FamilyInstance> lstLevelFireDoors, bool bOutsideRoom)
		{
			List<Room> list = new FilteredElementCollector(this.Doc, idView).OfCategory(BuiltInCategory.OST_Rooms).Cast<Room>().ToList<Room>();
			List<FamilyInstance> list2 = new List<FamilyInstance>();
			Transaction transaction = new Transaction(this.Doc, "CreateRoomTag");
			transaction.Start();
			try
			{
				foreach (object obj in this.Doc.get_PlanTopology(level).Circuits)
				{
					PlanCircuit planCircuit = (PlanCircuit)obj;
					if (!planCircuit.IsRoomLocated)
					{
						Room item = this.Doc.Create.NewRoom(null, planCircuit);
						list.Add(item);
					}
				}
				for (int i = 0; i < list.Count; i++)
				{
					Room room = list[i];
					if (room.Area > 1E-06)
					{
						int j = 0;
						while (j < lstStairs.Count)
						{
							XYZ stairsBtmRunPtOnXYPlane = StairsOperationInterface.GetStairsBtmRunPtOnXYPlane(this.Doc, lstStairs[j].Id);
							XYZ xyz = new XYZ(stairsBtmRunPtOnXYPlane.X, stairsBtmRunPtOnXYPlane.Y, level.Elevation);
							if (!room.IsPointInRoom(xyz))
							{
								j++;
							}
							else
							{
								IList<IList<BoundarySegment>> boundarySegments = room.GetBoundarySegments(new SpatialElementBoundaryOptions());
								List<ElementId> lstRoomWallIds = (from e in boundarySegments.FirstOrDefault<IList<BoundarySegment>>()
								select e.GetElement(this.Doc).Id).Distinct<ElementId>().ToList<ElementId>();
								List<FamilyInstance> list3 = (from door in lstLevelFireDoors
								where lstRoomWallIds.Contains(door.Host.Id)
								select door).ToList<FamilyInstance>();
								IEnumerable<Curve> enumerable = from seg in this.GetRoomBoundarySegments(room).FirstOrDefault<IList<BoundarySegment>>()
								select seg.GetCurve();
								List<FamilyInstance> list4 = new List<FamilyInstance>();
								foreach (FamilyInstance familyInstance in list3)
								{
									XYZ point = (familyInstance.Location as LocationPoint).Point;
									foreach (Curve curve in enumerable)
									{
										double z = curve.GetEndPoint(0).Z;
										XYZ xyz2 = new XYZ(point.X, point.Y, z);
										XYZ xyzpoint = curve.Project(xyz2).XYZPoint;
										if (xyz2.DistanceTo(xyzpoint) <= 0.0001)
										{
											list4.Add(familyInstance);
											break;
										}
									}
								}
								using (List<FamilyInstance>.Enumerator enumerator2 = list4.GetEnumerator())
								{
									while (enumerator2.MoveNext())
									{
										FamilyInstance fiFireDoor = enumerator2.Current;
										if (this.IsFireDoorFlipFacingOutsideRoom(fiFireDoor, room) != bOutsideRoom && list2.Find((FamilyInstance e) => e.Id == fiFireDoor.Id) == null)
										{
											list2.Add(fiFireDoor);
										}
									}
								}
								lstStairs.RemoveAt(j);
							}
						}
					}
				}
			}
			catch
			{
			}
			finally
			{
				transaction.RollBack();
			}
			return list2;
		}

		private void ViewPlanElemTreeViewForm_Load(object sender, EventArgs e)
		{
			base.Icon = Resource.YArchitechIcon;
			if (!this.ReadDlgData())
			{
				this.InitDlgDataByDef();
			}
			ViewPlanElemTreeViewForm.ECheckType eCheckType = this.m_eCheckType;
			if (eCheckType == ViewPlanElemTreeViewForm.ECheckType.eCheckFireDoorFlipFacing)
			{
				this.InitTreeViewByDoorFlipFacing();
				this.Text = "防火门开启方向检测结果";
				this.labelReMark.Text = "勾选确定调整，双击定位查看";
				return;
			}
			if (eCheckType != ViewPlanElemTreeViewForm.ECheckType.eCheckFireDoorHaveTagOrNot)
			{
				return;
			}
			this.InitTreeViewByTag();
			this.Text = "防火门未标注检测结果";
			this.labelReMark.Text = "勾选确定自动标注，双击定位查看";
		}

		private void ViewPlanElemTreeViewForm_FormClosed(object sender, FormClosedEventArgs e)
		{
			this.WriteDlgData();
		}

		private void btnSelAll_Click(object sender, EventArgs e)
		{
			this.UpdateTreeNodeCheckStatus(true);
		}

		private void btnSelNone_Click(object sender, EventArgs e)
		{
			this.UpdateTreeNodeCheckStatus(false);
		}

		private void btnSelReverse_Click(object sender, EventArgs e)
		{
			this.ReverseTreeNodeCheckStatus(this.treeView.Nodes);
		}

		private void btnOK_Click(object sender, EventArgs e)
		{
			try
			{
				this.m_lstElemIDs = new List<ElementId>();
				this.m_notDimedDoors = new List<NotDimedDoorWithView>();
				foreach (object obj in this.treeView.Nodes)
				{
					TreeNode treeNode = (TreeNode)obj;
					foreach (object obj2 in treeNode.Nodes)
					{
						TreeNode treeNode2 = (TreeNode)obj2;
						if (treeNode2.Checked)
						{
							FamilyInstance familyInstance = treeNode2.Tag as FamilyInstance;
							this.m_lstElemIDs.Add(familyInstance.Id);
							NotDimedDoorWithView notDimedDoorWithView = new NotDimedDoorWithView();
							notDimedDoorWithView.door = familyInstance;
							notDimedDoorWithView.inView = (treeNode.Tag as Autodesk.Revit.DB.View);
							this.m_notDimedDoors.Add(notDimedDoorWithView);
						}
					}
				}
			}
			catch
			{
			}
		}

		private void InitTreeViewByTag()
		{
			try
			{
				foreach (Autodesk.Revit.DB.ViewPlan viewPlan in this.m_lstViewPlan)
				{
					List<FamilyInstance> list = new FilteredElementCollector(this.Doc, viewPlan.Id).OfCategory(BuiltInCategory.OST_Doors).Cast<FamilyInstance>().ToList<FamilyInstance>().FindAll(new Predicate<FamilyInstance>(UtilityTools.IsValidFireDoor));
					if (list.Count >= 1)
					{
						List<FamilyInstance> list2 = new List<FamilyInstance>();
						foreach (FamilyInstance familyInstance in list)
						{
							if (!this.IfDoorHaveTagOrNot(familyInstance, viewPlan))
							{
								list2.Add(familyInstance);
							}
						}
						TreeNode treeNode = this.treeView.Nodes.Add(viewPlan.Name);
						treeNode.Tag = viewPlan;
						foreach (FamilyInstance familyInstance2 in list2)
						{
							treeNode.Nodes.Add(familyInstance2.Symbol.Name).Tag = familyInstance2;
						}
						this.treeView.ExpandAll();
					}
				}
			}
			catch
			{
			}
		}

		private bool IfDoorHaveTagOrNot(FamilyInstance elem, ViewPlan viewPlanCur)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.Doc, viewPlanCur.Id);
			filteredElementCollector.OfClass(typeof(IndependentTag)).OfCategory(BuiltInCategory.OST_DoorTags);
			IEnumerator<Element> enumerator = filteredElementCollector.GetEnumerator();
			{
				while (enumerator.MoveNext())
				{
					if (((IndependentTag)enumerator.Current).TaggedLocalElementId.IntegerValue == elem.Id.IntegerValue)
					{
						return true;
					}
				}
			}
			return false;
		}

		private void treeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
		{
			try
			{
				Element elem = e.Node.Tag as Element;
				this.ZoomSelElem(elem);
			}
			catch
			{
			}
		}

		private IList<IList<BoundarySegment>> GetRoomBoundarySegments(Room elemRoom)
		{
			if (elemRoom == null)
			{
				return null;
			}
			IList<IList<BoundarySegment>> result = null;
			try
			{
				result = elemRoom.GetBoundarySegments(new SpatialElementBoundaryOptions
				{
					StoreFreeBoundaryFaces = true,
                    SpatialElementBoundaryLocation = (SpatialElementBoundaryLocation)1
				});
			}
			catch
			{
			}
			return result;
		}

		private List<NotDimedDoorWithView> m_notDimedDoors;

		private List<ViewPlan> m_lstViewPlan;

		private List<ElementId> m_lstElemIDs;

		private ExternalCommandData m_cmdData;

		private ViewPlanElemTreeViewForm.ECheckType m_eCheckType;

		public enum ECheckType
		{
			eCheckFireDoorFlipFacing,
			eCheckFireDoorHaveTagOrNot
		}

		private class LevelComparer : IComparer<ViewPlan>
		{
			public LevelComparer(Autodesk.Revit.DB.Document doc)
			{
				this.m_doc = doc;
			}

			public int Compare(ViewPlan x, ViewPlan y)
			{
				try
				{
					Level level = this.m_doc.GetElement(x.GenLevel.Id) as Level;
					Level level2 = this.m_doc.GetElement(y.GenLevel.Id) as Level;
					return level.Elevation.CompareTo(level2.Elevation);
				}
				catch
				{
				}
				return 0;
			}

			private Document m_doc;
		}

		private class LevelIdComparer : IComparer<ElementId>
		{
			public LevelIdComparer(Autodesk.Revit.DB.Document doc)
			{
				this.m_doc = doc;
			}

			public int Compare(ElementId x, ElementId y)
			{
				try
				{
					Level level = this.m_doc.GetElement(x) as Level;
					Level level2 = this.m_doc.GetElement(y) as Level;
					return level.Elevation.CompareTo(level2.Elevation);
				}
				catch
				{
				}
				return 0;
			}

			private Document m_doc;
		}
	}
}
